package com.xxl.job.admin.core.util;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * local cache tool
 *
 * @author xuxueli 2018-01-22 21:37:34
 */
public class LocalCacheUtil {

  private static ConcurrentMap<String, LocalCacheData> cacheRepository = new ConcurrentHashMap<String, LocalCacheData>();   // 类型建议用抽象父类，兼容性更好；

  private static class LocalCacheData {

    private String key;
    private Object val;
    private long timeoutTime;

    public LocalCacheData() {
    }

    public LocalCacheData(String key, Object val, long timeoutTime) {
      this.key = key;
      this.val = val;
      this.timeoutTime = timeoutTime;
    }

    public String getKey() {
      return key;
    }

    public void setKey(String key) {
      this.key = key;
    }

    public Object getVal() {
      return val;
    }

    public void setVal(Object val) {
      this.val = val;
    }

    public long getTimeoutTime() {
      return timeoutTime;
    }

    public void setTimeoutTime(long timeoutTime) {
      this.timeoutTime = timeoutTime;
    }
  }


  /**
   * set cache
   *
   * @param key
   * @param val
   * @param cacheTime
   * @return
   */
  public static boolean set(String key, Object val, long cacheTime) {

    // clean timeout cache, before set new cache (avoid cache too much)
    cleanTimeoutCache();

    // set new cache
    if (key == null || key.trim().length() == 0) {
      return false;
    }
    if (val == null) {
      remove(key);
    }
    if (cacheTime <= 0) {
      remove(key);
    }
    long timeoutTime = System.currentTimeMillis() + cacheTime;
    LocalCacheData localCacheData = new LocalCacheData(key, val, timeoutTime);
    cacheRepository.put(localCacheData.getKey(), localCacheData);
    return true;
  }

  /**
   * remove cache
   *
   * @param key
   * @return
   */
  public static boolean remove(String key) {
    if (key == null || key.trim().length() == 0) {
      return false;
    }
    cacheRepository.remove(key);
    return true;
  }

  /**
   * get cache
   *
   * @param key
   * @return
   */
  public static Object get(String key) {
    if (key == null || key.trim().length() == 0) {
      return null;
    }
    LocalCacheData localCacheData = cacheRepository.get(key);
    if (localCacheData != null && System.currentTimeMillis() < localCacheData.getTimeoutTime()) {
      return localCacheData.getVal();
    } else {
      remove(key);
      return null;
    }
  }

  /**
   * clean timeout cache
   *
   * @return
   */
  public static boolean cleanTimeoutCache() {
    if (!cacheRepository.keySet().isEmpty()) {
      for (String key : cacheRepository.keySet()) {
        LocalCacheData localCacheData = cacheRepository.get(key);
        if (localCacheData != null
            && System.currentTimeMillis() >= localCacheData.getTimeoutTime()) {
          cacheRepository.remove(key);
        }
      }
    }
    return true;
  }

}
